<?php


namespace app\api\library\order\allInPayNotify;


use app\api\model\AllInPay;
use app\api\model\MallCollage;
use app\api\model\MallOrder;
use app\api\model\MallTradeRecordLog;
use app\api\model\MallUser;
use think\facade\Db;
use think\facade\Log;

class V
{
    public static function run()
    {
        Log::write('allInPayNotify');
        Log::write($_POST);
        try {
            $params = [];
            foreach ($_POST as $key => $val) {//动态遍历获取所有收到的参数,此步非常关键,因为收银宝以后可能会加字段,动态获取可以兼容由于收银宝加字段而引起的签名异常
                $params[ $key ] = $val;
            }
            if (count($params) < 1) {//如果参数为空,则不进行处理
                echo "error";
                exit();
            }
            if (AllInPay::ValidSign($params)) {//验签成功
                //此处进行业务逻辑处理
                echo "success";
            } else {
                echo "erro";
            }
            //处理微信数据
            [$dataArr, $order] = self::handleWechatData($params);
            //验证通过，封装更新订单状态方法
            self::afterPay($dataArr, $order);
            Log::write($params);
        } catch (\Exception $e) {
            
            Log::write($e);
            
            exit("fail");
        }
    }
    /**
     * 处理支付回调数据
     * @param $data
     * @return array
     * @throws array
     */
    public static function handleWechatData($params)
    : array
    {
        //订单编号
        $orderNo = $params[ 'cusorderid' ];
        //付款金额 单位元=>分
        $payPrice = (int) $params[ 'trxamt' ];
        //获取订单 包含验证订单号、付款金额
        $order = MallOrder::where('order_no', $orderNo)->find()->toArray();
        //取出所有数据
        $dataArr = [
            //三方订单编号trade_no
            'trade_no'  => $params[ 'chnltrxid' ],
            //支付方式pay_type 1.支付宝 2.微信
            'pay_mode'  => 2,
            //付款金额 pay_price 单位为分
            'pay_price' => $payPrice,
            //支付三方用户id 用于退款转账
            'buyer_id'  => $params[ 'acct' ],
            'open_id'   => $params[ 'acct' ],
            //支付时间
            //            'pay_time'  => date('Y-m-d H:i:s', strtotime($data->time_end)),
        ];
        return [$dataArr, $order];
    }
    
    /**
     * 付款后
     * @param $dataArr
     * @param $diagnoseOrder
     * @param $payMode
     * @throws \think\Exception
     */
    public static function afterPay($dataArr, $order)
    {
        //取出订单id
        $orderId = $order[ 'id' ];
        //订单编号
        $orderNo = $order[ 'order_no' ];
        //用户ID
        $userId = $order[ 'user_id' ];
        //余额支付部分
        $payBalance = $order[ 'pay_balance' ];
        //判断状态
        if ($order[ 'order_status' ] === 10) {
            //多方支付异步重复 记录日志
            $msg = 'pay notify repeat: ' . $orderNo;
            Log::warning($msg);
            exit("fail");
        }
        $balance = MallUser::where('id', $userId)->value('balance');
        try {
            //开启事务
            Db::startTrans();
            //修改订单状态
            $modOrder = ['pay_price' => $dataArr[ 'pay_price' ], 'transaction_id' => $dataArr[ 'trade_no' ], 'order_status' => 10];
            //添加交易记录
            $tradeLogData = [
                'user_id'     => $userId,
                'order_id'    => $orderId,
                'trade_type'  => 1,
                'amount'      => $dataArr[ 'pay_price' ],
                'create_time' => time(),
                'update_time' => time(),
            ];
            if (false === MallTradeRecordLog::insert($tradeLogData)) {
                _throwNewException('订单支付失败2');
            }
            if ($payBalance > 0) {
                $surBalance = $balance - $payBalance;
                //减去余额
                if (false === MallUser::where([['id', '=', $userId]])->update(['balance' => $surBalance])) {
                    _throwNewException('订单支付失败3');
                }
                //添加交易记录
                $tradeLogData = [
                    'user_id'     => $userId,
                    'order_id'    => $orderId,
                    'trade_type'  => 2,
                    'amount'      => $payBalance,
                    'balance'     => $surBalance,
                    'create_time' => time(),
                    'update_time' => time(),
                ];
                if (false === MallTradeRecordLog::insert($tradeLogData)) {
                    _throwNewException('订单支付失败4');
                }
            }
            //修改新手状态
            if (false === MallUser::where([['id', '=', $userId]])->update(['is_novice' => 0])) {
                _throwNewException('订单支付失败5');
            }
            
            if ($order[ 'u_collage_id' ] > 0) {
                $uCollage = MallCollage::where([['collage_id', '=', $order[ 'u_collage_id' ], 'fail_time', '=', null]])->find();
                if ( !empty($uCollage)) {
                    
                    $collageNum = MallCollage::where('collage_id', $order[ 'u_collage_id' ])->value('collage_num');
                    //已支付人数
                    $joinNum = MallCollage::where('collage_id', $order[ 'u_collage_id' ])->value('join_num');
                    if ($joinNum + 1 == $collageNum) {
                        MallOrder::finishCollage($order[ 'u_collage_id' ]);
                    }
                }
                
            }
            $collageId                = MallOrder::resolveCollage($order, $userId);
            $modOrder[ 'collage_id' ] = $collageId;
            if (false === MallOrder::where([['id', '=', $orderId]])->update($modOrder)) {
                _throwNewException('订单支付失败1');
            }
            //查询用户邀请人
            $promotionId = MallUser::where([['id', '=', $userId]])->value('promotion_id');
            if ( !empty($promotionId)) {
                Log::write('promotion');
                MallOrder::resolvePromotion($promotionId, $order);
            }
            Db::name('mall_goods')->where('id', $order[ 'goods_id' ])->inc('sales', 1)->update();
            Db::name('mall_goods')->where('id', $order[ 'goods_id' ])->inc('virtual_sales', 1)->update();
            // 提交事务
            Db::commit();
            //记录支付后，修改订单状态成功
            Log::Info('pay notify success:' . $orderNo);
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            throw new \think\Exception("orderNo:$orderNo " . $e->getMessage());
        }
    }
}